package com.cmcc.pcap.packet.util.pfcpUtile;

import com.cmcc.packet.entity.PfcpEntity;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.net.Inet4Address;
import java.net.Inet6Address;
import java.util.HashMap;
import java.util.Map;

public class UserPlaneIPResourceInformationUtil implements PfcpTypeUtil{
    private static Logger logger = LogManager.getLogger(UserPlaneIPResourceInformationUtil.class);

    Boolean assosi;
    Boolean assoni;
    int teidri;
    Boolean v6;
    Boolean v4;
    Boolean teidRange;
    Inet4Address Ipv4Address;
    Inet6Address Ipv6Address;
    String NetworkInstance;
    int sourceInterface;

    @Override
    public PfcpEntity.InformationElement analysisIe(byte[] sub_payload) {
        PfcpEntity.InformationElement peie = new PfcpEntity.InformationElement();
        try {
            peie.setType(((sub_payload[0] & 0xff) << 8) + (sub_payload[1] & 0xff));
            peie.setLength(((sub_payload[2] & 0xff) << 8) + (sub_payload[3] & 0xff));
            Map<String, String> dataMap = new HashMap<>();
            int source_interface_flag = (sub_payload[4] << 6) & 0x1;
            dataMap.put("assosi", String.valueOf(source_interface_flag));

            int network_instance_flag = (sub_payload[4] << 5) & 0x1;
            dataMap.put("assoni", String.valueOf(network_instance_flag));

            StringBuffer sb = new StringBuffer();
            sb.append((sub_payload[4]>>4)&0x1)
                    .append((sub_payload[4]>>3)&0x1)
                    .append((sub_payload[4]>>2)&0x1);
            dataMap.put("teidri", sb.toString());

            int v6_flag = (sub_payload[4] << 1) & 0x1;
            dataMap.put("v6", String.valueOf(v6_flag));

            int v4_flag = (sub_payload[4] << 0) & 0x1;
            dataMap.put("v4", String.valueOf(v4_flag));

            dataMap.put("TEID Range", String.valueOf(sub_payload[5] & 0xff));
            if(v4_flag==1) {
                if (sub_payload.length >= 6 + 4 * v4_flag) {
                    byte[] ipv4_byte = new byte[4];
                    System.arraycopy(sub_payload, 6, ipv4_byte, 0, 4);
                    dataMap.put("ipv4", String.valueOf(Inet4Address.getByAddress(ipv4_byte)));
                } else {
                    logger.error("Inadequate TLV length: %d", sub_payload.length);
                }
            }

            if(v6_flag==1) {
                if (sub_payload.length >= 6 + 4 * v4_flag + 16 * v6_flag) {
                    byte[] ipv6_byte = new byte[16];
                    System.arraycopy(sub_payload, 6 + 4 * v4_flag, ipv6_byte, 0, 16);
                    dataMap.put("ipv6", String.valueOf(Inet6Address.getByAddress(ipv6_byte)));
                } else {
                    logger.error("Inadequate TLV length: %d", sub_payload.length);
                }
            }

            if(network_instance_flag==1){
                if(sub_payload.length >= 6+4*v4_flag+16*v6_flag+4*network_instance_flag) {
                    byte[] network_instance_byte = new byte[8];
                    System.arraycopy(sub_payload, 6 + 4 * v4_flag + 16 * v6_flag, network_instance_byte, 0, 4);
                    dataMap.put("NetworkInstance", RFCUtil.rfc1035tofqdn(network_instance_byte));
                }else {
                    logger.error("Inadequate TLV length: %d", sub_payload.length);
                }
            }

            if(source_interface_flag==1){
                if(sub_payload.length >= 6+4*v4_flag+16*v6_flag+8*network_instance_flag+1*source_interface_flag) {
                    dataMap.put("SourceInterface", String.valueOf(sub_payload[6 + 4 * v4_flag + 16 * v6_flag + 8 * network_instance_flag] & 0xff));
                }else {
                    logger.error("Inadequate TLV length: %d", sub_payload.length);
                }
            }

            peie.setDataMap(dataMap);
        }catch (Exception e) {
            e.printStackTrace();
        }
        return peie;
    }
}
